<?php
/**
 * IG_ModelMapper
 *
 * @author mmxie
 * @copyright Copyright (c) 2009 Green Shore (http://www.iwgame.com)
 * @version $Id: ModelMapper.php 1110 2011-12-23 09:03:09Z mmxie $
 */
class IG_ModelMapper
{
    /**
     * @var IG_Model_DbTable
     */
    protected $_dbTable;

    protected $_adapter;

    protected $_model;

    public function __construct($model = null, $_adapter = null)
    {
        if ($model != null) {
            $this->_model = $model;
        } else {
            $modelName = substr(get_class($this), 0, -6);
            $this->_model = new $modelName();
        }

        if (null !== $_adapter) {
            if (is_array($_adapter)) {
                $this->_adapter = Zend_Db::factory($_adapter['adapter'], $_adapter);
            } else if ($_adapter instanceof Zend_Config ) {
                $this->_adapter = Zend_Db::factory($_adapter->adapter, $_adapter);
            } else if ($_adapter instanceof Zend_Db_Adapter_Abstract ) {
                $this->_adapter = $_adapter;
            } else {
                throw new Exception('Can not load the adapter by construct, the params is not correct');
            }
        }
    }

    /**
     * @return IG_Model
     */
    public function getModel()
    {
        return $this->_model;
    }

    /**
     * 设置默认的DbTable
     *
     * @param IG_Model_DbTable $dbTable
     * @return IG_ModelMapper
     * @throws Exception with Invalid table data gateway provided
     */
    public function setDbTable($dbTable)
    {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable($this->_adapter);
        }
        if (! $dbTable instanceof IG_Model_DbTable) {
            throw new Exception('Invalid table data gateway provided');
        }
        $this->_dbTable = $dbTable;
        return $this;
    }


    /**
     * Get the db-table, if null then create it.
     *
     * @return IG_Model_DbTable
     */
    public function getDbTable()
    {
        if (null === $this->_dbTable) {
            $class = str_replace('_Model_', '_Model_DbTable_', get_class($this->getModel()));
            $this->setDbTable($class);
        }
        return $this->_dbTable;
    }

    /**
     * @param int|IG_Model $model
     * @return int|bool    The number of rows deleted.
     */
    public function delete($id = null)
    {
        $primarys = $this->getDbTable()->getPrimary();
        if (empty($id)) {
            $where = $this->_getPrimaryCondition();
        } else {
            $where = array("`$primarys`=?" => $id);
        }
        return $this->getDbTable()->delete($where);
    }

    /**
     * Insert or update model.
     *
     * @param int $method
     * @return bool|int
     */
    public function save($method = null)
    {
        $data = $this->getModel()->getModifiedFields();
        if ($method == IG_Model::DUPLICATE) {
            return $this->getDbTable()->insertDuplicate($data);
        } else if ($method == IG_Model::REPLACE) {
            return $this->getDbTable()->replace($data);
        } else {
            $primarys = (array) $this->getDbTable()->getPrimary();
            $where = $this->_getPrimaryCondition();
            foreach ($primarys as $primary) {
                unset($data[$primary]);
            }

            if (count($primarys) != count($where)) {
                $result = $this->getDbTable()->insert($data);
                if ($result > 0) {
                    $this->getModel()->__set(array_shift($primarys), $result);
                }
                return $result;
            } else {
                return $this->getDbTable()->update($data, $where);
            }
        }
    }

    /**
     *
     * @param $id
     * @param $model IG_Model
     * @return IG_Model
     */
    public function find()
    {
        $result = call_user_func_array(array($this->getDbTable(), 'find'), func_get_args());
        switch (count($result)) {
            case 0:
                return ;
            break;

            case 1:
                return $result->current();

            default:
                return $result;
            break;
        }
    }

    /**
     * Get row's count of db-table
     *
     * @param array $where
     * @return int
     */
    public function fetchCount($where = null)
    {
        $select = $this->getDbTable()->fetchCount($where);
    }

    /**
     * 获取空字段数据
     * @return array
     */
    public function getEmptyData()
    {
        $data = array();
        foreach ($this->getDbTable()->info('cols') as $key) {
            $data[$key] = null;
        }
        return $data;
    }

    protected function _getPrimaryCondition()
    {
        $where = array();
        $primarys = (array) $this->getDbTable()->getPrimary();
        foreach ($primarys as $primary) {
            $priValue = $this->getModel()->__get($primary);
            if (!empty($priValue)) {
                $where["`$primary`=?"] = $priValue;
            }
        };
        return $where;
    }

    public function __call($method, $params)
    {
        return call_user_func_array(array($this->getDbTable(), $method), $params);
    }
}